home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1994 / MacHack 1994.toast / MacHack™94 / Miscellaneous / Randy Thelen / ThreadedBrot / Lib / DialogWindow.cp < prev    next >
Encoding:
Text File  |  1994-06-26  |  4.9 KB  |  213 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        DialogWindow.cp
  3.  
  4.     Contains:    Implementation of a base class for Modeless Dialogs
  5.                 
  6.     Written by: Dave Falkenburg
  7.  
  8.     Copyright:    © 1993-94 by Dave Falkenburg, all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.     
  12.     To Do:
  13.  */
  14.  
  15. #include    <Dialogs.h>
  16. #include    <Menus.h>
  17. #include    <Desk.h>
  18.  
  19. #include    "DialogWindow.h"
  20. #include    "AppLib.h"
  21.  
  22.  
  23. TDialogWindow::TDialogWindow(DialogTemplateID dialogTemplateID)
  24.     {
  25.     fTemplateID = dialogTemplateID;
  26.     CreateWindow(kNormalWindow);
  27.     }
  28.  
  29.  
  30. WindowPtr
  31. TDialogWindow::MakeNewWindow(WindowPtr behindWindow)
  32.     {
  33.     return GetNewDialog(fTemplateID,nil,behindWindow);
  34.     }
  35.  
  36.  
  37. ////////////////////////////////////////////////////////////////////////////////////
  38. //
  39. //    EventFilter strategy for Dialog Window
  40. //
  41. //    Because of the need to patch and unpatch FrontWindow when calling IsDialogEvent
  42. //    and DialogSelect, only do these things when a Modless Dialog is the frontmost
  43. //    window. (e.g., it’s event filter is active)
  44. //
  45. //    NOTE: We always pass events through, except when an item has been hit.
  46. //
  47. //    You may be thinking that it is easier to just rewrite the Dialog Manager in
  48. //    this program. You’re probably right.
  49.  
  50. pascal    WindowPtr
  51. FrontWindowPatchForDialogs()
  52.     {
  53.     return FrontNonFloatingWindow();
  54.     }
  55.  
  56. #define    uppFrontWindowPatchProcInfo (kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(WindowPtr))))
  57.  
  58. UniversalProcPtr FrontWindowPatchUPP
  59. = (UniversalProcPtr) NewRoutineDescriptor((ProcPtr) &FrontWindowPatchForDialogs,uppFrontWindowPatchProcInfo,GetCurrentISA());
  60.  
  61.  
  62. Boolean
  63. TDialogWindow::EventFilter(EventRecord *theEvent)
  64.     {
  65.     UniversalProcPtr    oldFrontWindow = GetToolboxTrapAddress(_FrontWindow);
  66.     DialogPtr            aDialog;
  67.     Boolean                eventHasBeenGobbled = false;
  68.     short                aDialogItem;
  69.     short                oldWindowKind;
  70.     
  71.     //    Don’t snarf keypresses meant for menus
  72.     if ((theEvent->what == keyDown) && (theEvent->modifiers & cmdKey))
  73.         return false;
  74.         
  75.     //    Patch in our version of FrontWindow so that IsDialogEvent will do the right
  76.     //    thing. DialogManager should check both frontmost floating and frontmost
  77.     //    non-floating windows, however we don’t support floating dialogs.
  78.     SetToolboxTrapAddress(FrontWindowPatchUPP,_FrontWindow);
  79.  
  80.     //    Jam the windowKind of our dialog window back to dialogKind so that the
  81.     //    Dialog Manager can recognize our window as a dialog window.
  82.     oldWindowKind = ((WindowPeek) fWindow)->windowKind;
  83.     ((WindowPeek) fWindow)->windowKind = dialogKind;
  84.     
  85.     if (IsDialogEvent(theEvent))
  86.         if (DialogSelect(theEvent,&aDialog,&aDialogItem))
  87.             eventHasBeenGobbled = true;
  88.  
  89.     //    Restore the windowKind
  90.     ((WindowPeek) fWindow)->windowKind = oldWindowKind;
  91.  
  92.     //    Put FrontWindow back the way it really belongs
  93.     SetToolboxTrapAddress((UniversalProcPtr) oldFrontWindow,_FrontWindow);
  94.  
  95.     if (eventHasBeenGobbled)
  96.         {
  97.         ItemHit(aDialogItem);
  98.         return true;
  99.         }
  100.  
  101.     return(false);
  102.     }
  103.  
  104.  
  105. void
  106. TDialogWindow::Idle(EventRecord * /* anEvent */)
  107.     {
  108.     }
  109.  
  110.  
  111. void
  112. TDialogWindow::Activate(Boolean activating)
  113.     {
  114.     /*    (De)activates are NOT automagically handled because our floating
  115.      *    windows prevent real activate events from ever being generated
  116.      *    for any non-floaters windows.
  117.      *
  118.      *    Our strategy is to fool the dialog manager into thinking that
  119.      *    things are still fine by passing it a fake (de)activate event.
  120.      *
  121.      *    Luckily, we don’t have to patch FrontWindow to make DialogSelect
  122.      *    work for activate and update events.
  123.      */
  124.     
  125.     EventRecord            fakeEvent;
  126.         
  127.     OSEventAvail(0,&fakeEvent);        //    Get an intialized, but otherwise empty event record
  128.     
  129.     fakeEvent.what = activateEvt;
  130.     fakeEvent.message = (unsigned long) fWindow;
  131.     if (activating)
  132.         fakeEvent.modifiers |= activeFlag;
  133.     else
  134.         fakeEvent.modifiers &= ~activeFlag;
  135.  
  136.     //    Pass event on to DialogSelect
  137.     
  138.     DialogPtr    aDialog;
  139.     short        aDialogItem;
  140.     
  141.     (void) DialogSelect(&fakeEvent,&aDialog,&aDialogItem);
  142.     }
  143.     
  144.  
  145. void
  146. TDialogWindow::Draw(void)
  147.     {
  148.     //    Automagically handled by Dialog Manager when we are
  149.     //    the frontmost window, but not at other times because
  150.     //    we only set the windowKind to dialogKind inside our
  151.     //    EventFilter (which is only active when we are frontmost).
  152.         
  153.     UpdateDialog((DialogPtr) fWindow, fWindow->visRgn);
  154.     }
  155.     
  156.     
  157. void
  158. TDialogWindow::Click(EventRecord * /* anEvent */)
  159.     {
  160.     /*    The only time this method is called is to handle a click
  161.      *    when the dialog window isn’t frontmost. All other times,
  162.      *    DialogSelect will do everything for us.
  163.      *
  164.      *    If our dialog contains useritems with the ability to
  165.      *    be the source of a drag we’d need to start drag tracking
  166.      *    in here.
  167.      */
  168.      
  169.     Select();
  170.     }
  171.  
  172.  
  173.  
  174. Boolean
  175. TDialogWindow::CanEdit(void)
  176.     {
  177.     return(true);
  178.     }
  179.  
  180.     
  181. void
  182. TDialogWindow::DoEditMenu(short item)
  183.     {
  184.     switch (item+accMenu)
  185.         {
  186.         case    accUndo:
  187.             break;
  188.             
  189.         case    accCut:
  190.             DlgCut((DialogPtr) &fWindow); 
  191.             break;
  192.             
  193.         case    accCopy:
  194.             DlgCopy((DialogPtr) &fWindow); 
  195.             break;
  196.             
  197.         case    accPaste:
  198.             DlgPaste((DialogPtr) &fWindow); 
  199.             break;
  200.             
  201.         case    accClear:
  202.             DlgDelete((DialogPtr) &fWindow); 
  203.             break;
  204.         }
  205.     }
  206.  
  207.  
  208. void
  209. TDialogWindow::ItemHit(short /* theItem */)
  210.     {
  211.     /*    Override this function to handle dialog items */
  212.     }
  213.